package com.baoyouqun.API.sms;

import com.baoyouqun.entity.SmsSendLimit;
import com.baoyouqun.entity.SmsVerification;
import com.baoyouqun.mapper.SmsMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Random;

@Service
public class SmsService {

    // 验证码有效期(分钟)
    private static final int CODE_EXPIRE_MINUTES = 5;
    // 同一手机号发送间隔(秒)
    private static final int SEND_INTERVAL_SECONDS = 60;
    // 同一手机号每日最大发送次数
    private static final int DAILY_MAX_SEND_COUNT = 10;
    // 验证码长度
    private static final int CODE_LENGTH = 6;

    private final AliyunSmsClient aliyunSmsClient;
    private final SmsMapper smsMapper;

    @Autowired
    public SmsService(AliyunSmsClient aliyunSmsClient, SmsMapper smsMapper) {
        this.aliyunSmsClient = aliyunSmsClient;
        this.smsMapper = smsMapper;
    }

    /**
     * 发送短信验证码
     *
     * @param phone 手机号
     * @param scene 业务场景
     * @return 发送结果
     */
    @Transactional
    public String sendVerificationCode(String phone, String scene) {
        // 1. 验证手机号格式
        if (!isValidPhone(phone)) {
            return "手机号格式不正确";
        }

        // 2. 验证业务场景
        if (!isValidScene(scene)) {
            return "不支持的业务场景";
        }

        // 3. 验证发送频率限制
        String limitResult = checkSendLimit(phone);
        if (limitResult != null) {
            return limitResult;
        }

        // 4. 生成验证码
        String code = generateVerificationCode();

        try {
            // 5. 调用阿里云API发送短信
            boolean sendSuccess = aliyunSmsClient.sendVerificationCode(phone, code, CODE_EXPIRE_MINUTES);
            if (!sendSuccess) {
                return "短信发送失败，请稍后重试";
            }

            // 6. 保存验证码记录
            SmsVerification verification = new SmsVerification();
            verification.setPhone(phone);
            verification.setCode(code);
            verification.setScene(scene);
            verification.setSendTime(LocalDateTime.now());
            verification.setExpireTime(LocalDateTime.now().plusMinutes(CODE_EXPIRE_MINUTES));
            smsMapper.saveVerification(verification);

            // 7. 更新发送限制记录
            updateSendLimit(phone);

            return "success";
        } catch (Exception e) {
            // 记录异常日志
            e.printStackTrace();
            return "发送过程中出现错误，请稍后重试";
        }
    }

    /**
     * 验证验证码
     *
     * @param phone 手机号
     * @param scene 业务场景
     * @param code  验证码
     * @return 验证结果
     */
    @Transactional
    public boolean verifyCode(String phone, String scene, String code) {
        // 1. 查询有效的验证码
        LocalDateTime now = LocalDateTime.now();
        return smsMapper.findValidVerification(phone, scene, now)
                .filter(verification -> verification.getCode().equals(code))
                .map(verification -> {
                    // 2. 标记为已使用
                    smsMapper.markAsUsed(verification.getId());
                    return true;
                })
                .orElse(false);
    }

    /**
     * 验证手机号格式
     */
    private boolean isValidPhone(String phone) {
        // 简单的手机号验证正则，可根据实际需求调整
        return phone != null && phone.matches("^1[3-9]\\d{9}$");
    }

    /**
     * 验证业务场景
     */
    private boolean isValidScene(String scene) {
        // 支持的业务场景
        return "register".equals(scene) || "login".equals(scene) || "reset".equals(scene);
    }

    /**
     * 检查发送限制
     */
    private String checkSendLimit(String phone) {
        LocalDate today = LocalDate.now();
        LocalDateTime now = LocalDateTime.now();

        // 查询当日发送记录
        return smsMapper.findSendLimit(phone, today)
                .map(limit -> {
                    // 检查每日发送次数限制
                    if (limit.getSendCount() >= DAILY_MAX_SEND_COUNT) {
                        return "今日验证码发送次数已达上限，请明日再试";
                    }

                    // 检查发送间隔限制
                    if (limit.getLastSendTime() != null) {
                        long secondsBetween = ChronoUnit.SECONDS.between(limit.getLastSendTime(), now);
                        if (secondsBetween < SEND_INTERVAL_SECONDS) {
                            return "验证码发送过于频繁，请" + (SEND_INTERVAL_SECONDS - secondsBetween) + "秒后再试";
                        }
                    }
                    return null;
                })
                .orElse(null);
    }

    /**
     * 更新发送限制记录
     */
    private void updateSendLimit(String phone) {
        LocalDate today = LocalDate.now();
        LocalDateTime now = LocalDateTime.now();

        smsMapper.findSendLimit(phone, today)
                .ifPresentOrElse(
                        limit -> smsMapper.updateSendLimit(limit.getId(), now),
                        () -> {
                            SmsSendLimit newLimit = new SmsSendLimit();
                            newLimit.setPhone(phone);
                            newLimit.setSendDate(today);
                            newLimit.setSendCount(1);
                            newLimit.setLastSendTime(now);
                            smsMapper.insertSendLimit(newLimit);
                        }
                );
    }

    /**
     * 生成指定长度的数字验证码
     */
    private String generateVerificationCode() {
        Random random = new Random();
        StringBuilder code = new StringBuilder();
        for (int i = 0; i < CODE_LENGTH; i++) {
            code.append(random.nextInt(10));
        }
        return code.toString();
    }
}
